在这个时代,越来越多的网站已经开始进化成web应用了:
- 越来越多的javascript运用在页面
- 在现代的浏览器上实现更多的功能
- 更少的整页重加载
结果必然是会导致客户端上存在着大量的代码需要去维护、开发。
大量的代码库需要被组织起来,所以模块系统提供了一个选择,它将可以把你的代码模块划分为各个小模块。
有很多不同的标准去定义依赖关系和导出值:- script 标签 风格(非模块系统)
- CommonJS
- AMD
- ES6 模块
- 还有更多...
模块导出到全局对象的接口, 即window对象。模块可以访问全局对象的依赖借口。
- 得注意全局对象是否冲突
- 得注意文件加载顺序
- 开发人员必须解决模块/库之间的依赖关系
- 在大型项目下,代码/文件将会越来越庞大并且后期将难以维护
- 服务器端模块可以重用
- 已经有很多这种风格的模块(npm)
- 非常简单、易用
- 阻塞调用不太适合于网络环境,因为网络请求是异步的
- 不能并行加载多个模块
- node.js (服务器端)
- browserify
- modules-webmake (编译成一个包)
- wreq (客户端)
- 适用于网络中的异步请求方式
- 多个模块并行加载
- 编码开销大(额外代码多)
- 更难读写
了解更多commonjs和amd 模式,在这里推荐阮一峰老师的好文: 传送门
为了支持模块系统,ecmaScript6 增加了一些新的语法来支持它 ``` import "jquery"; export function doStuff() {} module "localModule" {} ```- 静态分析简单
- 未来ES的标准
- 本地浏览器支持需要时间
- 暂时还很少有运用es6风格的模块
传输模块有2种极端方式:
- 每个模块为一个请求
- 所有模块打包成一个请求
两种都是被广泛使用的,但是两者都不是最佳方式:
-
每个模块为一个请求
- 优势: 只有需要的模块才会被传输
- 缺陷: 太多请求开销导致页面请求阻塞延迟,应用启动慢
-
所有模块来自一个请求
- 优势: 少量请求开销,少量阻塞延迟,页面加载快
- 缺陷: 不需要的模块也会被传输
比如:编译所有模块时,可以把模块分成多个更小的块
这样的话,我们可以得到多个较小的文件请求,不必要的模块只会在需要加载的页面下才会被请求,初始请求不会加载全部的代码库。
备注:这个想法是来自谷歌的GWT
了解更多 代码分割
为什么模块系统只帮助开发者去模块化js而已?实际项目开发上还有很多静态资源也需要一起被模块化,如:- css样式
- 图像
- web字体
- html模版
- 更多...
还有:
- coffeescript 转换成 javascript
- less/sass 样式 转换成 css 样式
- jade templates → javascript which generates html
- i18n files → something
- 更多...
这些应该也要有简单的方式去加载,如:
require("./style.css");
require("./style.less");
require("./template.jade");
require("./image.png");
以上的种种原因就是产生webpack的动机。